﻿//
// *************************************************************************************
// WP-Framework
// 
// Developed by
// Lukas Kretschmar (lkretschmar.dev@bluewin.ch)
//
// Switzerland, Copyright (c) 2013 lkretschmar
// This content is released under the MIT License (http://opensource.org/licenses/MIT).
//     
// *************************************************************************************
//
//
			

using System;
using System.Linq.Expressions;
using KretschIT.WP_Fx.EasyMoq.Calls.Properties;
using System.Collections.Generic;
using KretschIT.WP_Fx.Core.Validation;
using KretschIT.WP_Fx.Core.Converters;
using System.Reflection;

namespace KretschIT.WP_Fx.EasyMoq.Calls
{
    internal class PropertyHandler<T> : IPropertyHandler<T>
    {
        private readonly List<IPropertyMock<T>> properties = new List<IPropertyMock<T>>();
        private readonly T obj;

        public PropertyHandler(T obj)
        {
            this.obj = obj;
        }

        public IPropertyMock<T> Setup(MemberExpression property)
        {
            It.IsNotNull(() => property);

            return this.GetProperty(property.Member);
        }

        private IPropertyMock<T> GetProperty(MemberInfo property)
        {
            var p = this.GetExistingProperty(property);
            if (p == null)
            {
                p = new PropertyMock<T>(property, this.obj);
                this.properties.Add(p);
            }
            return p;
        }

        private IPropertyMock<T> GetExistingProperty(MemberInfo property)
        {
            foreach (var p in this.properties)
            {
                if (p.Is(property))
                {
                    return p;
                }
            }
            return null;
        }

        public object GetValue(MemberExpression property)
        {
            It.IsNotNull(() => property);

            var p = this.GetProperty(property.Member);
            return p.Value;
        }

        public void SetValue(MemberExpression property, object value)
        {
            It.IsNotNull(() => property);

            var p = this.GetProperty(property.Member);
            p.Value = value;
        }

        public void SetValue(PropertyInfo property, object value)
        {
            It.IsNotNull(() => property);

            var p = this.GetProperty(property);
            p.Value = value;
        }

        public int GetterCalls(MemberExpression property)
        {
            if (property == null)
            {
                return 0;
            }
            return this.CallsTo(p => p.GetterCalls, property.Member);
        }

        public int SetterCalls(MemberExpression property)
        {
            if (property == null)
            {
                return 0;
            }
            return this.CallsTo(p => p.SetterCalls, property.Member);
        }

        public int SetterCalls(PropertyInfo property)
        {
            if (property == null)
            {
                return 0;
            }
            return this.CallsTo(p => p.SetterCalls, property);
        }

        private int CallsTo(Func<IPropertyMock<T>, int> calls, MemberInfo property)
        {
            return calls(this.GetProperty(property));
        }
    }
}
